package com.lanou3g.demo;

import com.lanou3g.demo.zoo.Animal;
import com.lanou3g.demo.zoo.Feeder;
import com.lanou3g.demo.zoo.Mouse;
import com.lanou3g.demo.zoo.Penguin;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Penguin penguin = new Penguin("QQ", 1001);
        penguin.setId(1001);
        penguin.setName("QQ");
        penguin.eat();
        penguin.sleep();
        penguin.introduction();
        penguin.catchFish();

        Mouse mouse = new Mouse("米老鼠", 1002);
        mouse.setName("米老鼠");
        mouse.setId(1002);
        mouse.eat();
        mouse.sleep();
        mouse.introduction();
        mouse.stealOil();

        /*
        final 关键字
        它可以修饰类/方法/属性,
        修饰类, 那么该类不能被继承;
        修饰方法, 那么该方法不能被重写(覆写);
        修饰属性, 那么该属性的值不能被改变.
         */

        /*
        作业
        家庭: 父亲/母亲/孩子
        都有name age属性
        都有打印自己属性的方法

        男人类: 方法 给xxx和xxx挣钱
        女人类: 方法 给xxx和xxx做饭
        孩子类: 方法 xxx和xxx辅导xxx做作业

        家庭类: 三个属性, 男人 女人 孩子

        方法 xxx和xxx和xx去旅游


         */
//        Man man = new Man();
//        Woman woman = new Woman();
//        Child child = new Child();
//
//        Family f = new Family(man, woman, child);

        Animal a1 = new Animal("蛤蟆", 1);
        Animal a2 = new Animal("蛤蟆", 1);
        Animal[] animals = {a1, a2};
//        System.out.println(a1 == a2);
//        System.out.println(a1.equals(a2));

        /*
        直接打印一个对象的时候, 实际上在打印该对象的
        toString()方法的返回值.
        那么我们可以重写该方法, 自定义打印的内容
         */
        System.out.println(Arrays.toString(animals));

        penguin.eat();
        mouse.eat();

        System.out.println("------多态------");
        /*
        多态的原则:
        当调用某个对象的某个方法时,
        系统会看这个对象的真实类型是什么,
        调用的永远都是这个真实对象的方法
         */
        // 多态的表现实行
        // 1. 父类声明对象 由子类初始化(创建对象)
//        Penguin p = new Mouse("", 2); 错误的
        Animal animal1 = new Penguin("企鹅", 1003);
        Animal animal2 = new Mouse("老鼠", 1004);
        animal1.eat();
        animal2.eat();
        Object obj = animal1;
        System.out.println(obj.toString());

        // 2. 如果一个方法的参数中需要传递某个类型的参数,
        // 那么该类型的子类对象都可以进行传递
        Feeder feeder = new Feeder();
        feeder.feed(penguin);
        feeder.feed(mouse);
        feeder.feed(animal1);
        feeder.feed(animal2);

        // 3. 如果一个方法的返回值是某个类型,
        // 那么该类型的所有子类对象都可以作为返回值
        Animal a = feeder.catchOne(Feeder.TYPE_M);
        feeder.feed(a);
        if (a instanceof Penguin){
            Penguin p = (Penguin)a;
            p.catchFish();
        } else if (a instanceof Mouse){
            Mouse m = (Mouse) a;
            m.stealOil();
        }

        /*

        英雄类有移动和攻击的方法.
        英雄的子类有法师/战士等等其他类型的英雄.

        玩家类可以控制英雄进行移动和攻击,
        并且可以随时切换英雄.
        玩家分为大神和菜鸟.
        在攻击时大神可以使用英雄多次攻击, 菜鸟只能攻击一次.

         */

    }
}
